#include "MediaSelectionList.h"

#include <QBoxLayout>
#include <QAction>
#include <QFileInfo>
#include <QPushButton>
#include <QScrollBar>
#include <qcoreevent.h>
#include <QKeyEvent>
#include <QTimer>
#include <QDebug>
#include <QImageReader>

#include <math.h>
#include "ImageThumbnailThread.h"
#include "wpscrollarea.h"
#include "CheckableListItem.h"

#include "ProgressDialog.h"


MediaSelectionList::MediaSelectionList(const QStringList& aInitialSelections, MediaType type, QWidget* aParent)
    : MDragWidget(aParent), iInitialSelections(aInitialSelections)
    , iProgressDialog(0)
    , iMediaType(type)
{
    QVBoxLayout* layout = new QVBoxLayout(this);
    layout->setSpacing(0);
    layout->setContentsMargins(0, 0, 0, 0);
    iScrollArea = new WPScrollArea(this);
    iScrollArea->setFocusPolicy(Qt::NoFocus);
    layout->addWidget(iScrollArea);

    if(iMediaType != Videos) {
        // delayed update once idle
        connect(iScrollArea->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(UpdateThumbnailsTimeout()));
        connect(&iScrollTimer, SIGNAL(timeout()), this, SLOT(UpdateThumbnails()));
        
        // update immediately
        connect(iScrollArea->verticalScrollBar(), SIGNAL(sliderReleased()), this, SLOT(UpdateThumbnails()));

#ifndef Q_WS_MAEMO_5
         // finger-scroll released
        connect(iScrollArea, SIGNAL(ScrollingStopped()), this, SLOT(UpdateThumbnails()));
#endif
    }

    QAction* leftSoftKey = new QAction(tr("Select"), this);
    connect(leftSoftKey, SIGNAL(triggered()), this, SLOT(ItemsSelected()));
    leftSoftKey->setSoftKeyRole(QAction::PositiveSoftKey);
    //addAction(leftSoftKey);
    QAction* rightSoftKey = new QAction(tr("Cancel"), this);
    connect(rightSoftKey, SIGNAL(triggered()), this, SLOT(CancelClicked()));
    rightSoftKey->setSoftKeyRole(QAction::NegativeSoftKey);
    //addAction(rightSoftKey);

    setLayout(layout);

    iThumbnailThread = new ImageThumbnailThread(QSize(80, 80), this); // TODO: Size
    iThumbnailThread->start(QThread::LowPriority);

    iScrollTimer.setSingleShot(true);
    
    // Finally add the data for WPCustomViewBasicData

    if(iMediaType == Images) {
        iTitleText = tr("Images");
        iTabText = tr("Images");
    } else if(iMediaType == Videos) {
        iTitleText = tr("Videos");
        iTabText = tr("Videos");
    } else {
        iTitleText = "";
        iTabText = "";
    }
    
    
    iHappyAction = leftSoftKey;
    iSadAction = rightSoftKey;
}

MediaSelectionList::~MediaSelectionList()
{
    if (iSearchThread)
    {
        if (iSearchThread->isRunning())
        {
            iSearchThread->Cancel();
            // Bump priority to make it terminate fast
            iSearchThread->setPriority(QThread::HighestPriority);
            iSearchThread->wait();
        }
        delete iSearchThread;
        iSearchThread = 0;
    }
    
    if (iThumbnailThread)
    {
        if (iThumbnailThread->isRunning())
        {
            iThumbnailThread->Cancel();
            // Bump priority to make it terminate fast
            iThumbnailThread->setPriority(QThread::HighestPriority);
            iThumbnailThread->wait();
        }
        delete iThumbnailThread;
    }
}

void MediaSelectionList::SearchMedia()
{
    delete iProgressDialog;
    iProgressDialog = 0;
    iProgressDialog = new ProgressDialog(this, true);
    connect(iProgressDialog, SIGNAL(canceled()), this, SLOT(CancelSearch()));
    
    emit TaskStarted(EIdle);
    iSearchThread = new MediaSearchThread(this);
    qRegisterMetaType<QFileInfo>("QFileInfo");
    connect(iSearchThread, SIGNAL(finished()), this, SLOT(ThreadFinished()));
    
    switch(iMediaType)
        {
        case Images:
            iProgressDialog->ShowTaskProgress(tr("Photos are loading..."));
            iSearchThread->setSearchType(MediaSearchThread::SearchImages);
            break;
        case Videos:
            iProgressDialog->ShowTaskProgress(tr("Videos are loading..."));
            iSearchThread->setSearchType(MediaSearchThread::SearchVideos);
        }
    iSearchThread->start(QThread::LowPriority);
}

void MediaSelectionList::CancelClicked()
{
    if(iMediaType == Images)
        emit ImagesSelected(iInitialSelections, QList<QPixmap>());
    else if (iMediaType == Videos)
        emit VideosSelected(iInitialSelections);
}

void MediaSelectionList::ItemsSelected()
{
    QStringList filenames;
    QList<QPixmap> thumbnails;
    const int count = iItems.count();
    for (int i = 0; i < count; i++)
    {
        if (iItems[i]->IsChecked()) {
            filenames.append(iItems[i]->ItemId());
            if (iItems[i]->GetThumbnail() == NULL ||
                iItems[i]->GetThumbnail()->isNull()) {
                QImageReader reader;
                reader.setFileName(iItems[i]->ItemId());
                QSize imageSize = reader.size();
                imageSize.scale(QSize(80, 80), Qt::KeepAspectRatio);
                reader.setScaledSize(imageSize);
                thumbnails.append(QPixmap::fromImage(reader.read()));
            } else {
                thumbnails.append(*iItems[i]->GetThumbnail());
            }
        }
    }

    if(iMediaType == Images)
        emit ImagesSelected(filenames, thumbnails);
    else if (iMediaType == Videos)
        emit VideosSelected(filenames);

#ifdef Q_WS_MAEMO_5
    close();
#endif
}

void MediaSelectionList::ThreadFinished()
{   
    if(!SearchIsCanceled()) {
        PopulateLayout();
    }
    
    emit TaskFinished(EIdle);
    if(iProgressDialog) {
        delete iProgressDialog;
        iProgressDialog = 0;
    }
    
    // The search might be canceled during PopulateLayout, so check the state here again
    if(SearchIsCanceled()) {
        emit SearchCanceled();
    } else {
        emit SearchComplete();
    }
    
    // finally delete thread
    delete iSearchThread;
    iSearchThread = NULL;
}

bool MediaSelectionList::MDragWidgetIsDragging() const
{
    return iScrollArea->IsDragging();
}

QSize MediaSelectionList::VisibleSize() const
{
    return iScrollArea->GetVisibleContentSize();
}

QString MediaSelectionList::FormatFileSize(int aFileSize) const
{
    // TODO make something more fancy
    return QString::number(int(aFileSize / 1024)) + tr(" kB");
}

void MediaSelectionList::PopulateLayout()
{
    if (!iScrollArea->widget())
        iScrollArea->InitLayout();
    
    // hide content to maybe make things faster?
    iScrollArea->widget()->hide();
    
    // Does this do any good if hidden?
    //iScrollArea->widget()->setFixedHeight( 80 * list.count());
    
    int i = 0;
    MediaSearchThread::FileInfoList const & list = iSearchThread->InfoList();
    for(MediaSearchThread::FileInfoList::const_iterator it = list.begin(); it != list.end(); ++it) {
        createItem(*it);
        
        // Process events after every 10 items to keep ui responsive
        if(++i == 10) {
            i = 0;
            QApplication::processEvents();
            
            // this might be cancelled during processEvents();
            if(SearchIsCanceled()) {
                return;
            }
        }
    }
    
    // show again
    iScrollArea->AddStretch();
    iScrollArea->widget()->show();
    
    if(iMediaType != Videos)
        QTimer::singleShot(1000, this, SLOT(UpdateThumbnails()));
}

void MediaSelectionList::createItem(const QFileInfo& aFileInfo)
{
    CheckableListItem* item = new CheckableListItem(aFileInfo.filePath(),
                                                    iInitialSelections.contains(aFileInfo.filePath()),
                                                    *iThumbnailThread,
                                                    *this);
    item->setFixedHeight(80);
    item->InitImageItem(aFileInfo.fileName(),
                        WPNetworkEngine::LocalizedTime(aFileInfo.lastModified()),
                        FormatFileSize(aFileInfo.size()));

    iScrollArea->addWidget(item);
    iItems.append(item);
}

void MediaSelectionList::setFocus()
{
    if (iItems.count() > 0)
        iItems.at(0)->setFocus();
    else
        iScrollArea->setFocus();
}

void MediaSelectionList::UpdateThumbnails()
{
    if(iMediaType == Videos) { return; }
    
    // qDebug() << "ImageSelectionList::UpdateThumbnails";

    // invalidate timer
    iScrollTimer.stop();

    // TODO: Binary search to decrease from O(N) to O(log(N))
    int i = 0;
    while (i < iItems.size() &&
           iItems[i]->mapTo(iScrollArea->widget(), QPoint(0,0)).y() + iItems[i]->size().height() <
           -iScrollArea->widget()->pos().y())
    {
        i++;
    }
    while (i < iItems.size() && iItems[i]->mapTo(iScrollArea->widget(), QPoint(0,0)).y() <
           -iScrollArea->widget()->pos().y() + iScrollArea->viewport()->size().height())
    {
        if (!iItems[i]->ThumbnailCreated())
        {
            iItems[i]->CreateThumbnail();
        }
        i++;
    }
}

void MediaSelectionList::UpdateThumbnailsTimeout ()
{
    // qDebug() << "ImageSelectionList::UpdateThumbnailsTimeout";

    // start or restart
    iScrollTimer.start(100);
}

void MediaSelectionList::CancelSearch()
{
    iSearchThread->Cancel();
}
